hexo icarus、golang、google analytics自行实现访问量统计(三)

前言

之前实现的版本只能点开文章查看访问量,这次打算改造一波,让文章的访问量在首页就能显示。
目前实现的后端只支持针对单个地址查询访问量,如果通过多次请求查询这样对页面的加载十分不友好,所以这次要折腾的内容是golang后端支持批量查询与icarus前端批量处理文章地址。

coding

后端篇

功能实现

上次已经实现了能够查询单个地址访问量的handler,这次新增一个handler用来批量读取访问量数据。
首先是请求的结构体,用一个slice来接收路径列表。

1
2
3
type BatchReq struct {
    Path []string `json:"path"`
}

批量查询handler实现如下,由于icarus获取到的page对象的路径是没有最前面的斜杠的,所以要么在前端拼上斜杠,要么在后端拼上斜杠来查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func BatchHandler(w http.ResponseWriter, r *http.Request) {
    allBytes, err := ioutil.ReadAll(r.Body)
    if err != nil {
        return
    }
    req := BatchReq{}
    err = json.Unmarshal(allBytes, &req)
    if err != nil {
        return
    }
    pvList := make([]int, 0)
    for _, path := range req.Path {
        unEscapePath, _ := url.QueryUnescape(path)
        pvList = append(pvList, service.data.PvMap["/"+unEscapePath])
    }


    bytes, _ := json.Marshal(map[string]interface{}{
        "pv": pvList,
    })
    w.Write(bytes)
    service.lastVisitTime = time.Now().Unix()
}

测试

下面拿postman来测试一下,挑两篇文章的地址请求,可以看到返回了访问量的列表。
postman测试后端

前端篇

上次实现的只会在非主页出现,所以这次要先改造一下article.jsx,把!index去掉并在标签内加上page.path,方便我们用js获取文章的路径。

1
2
3
{plugins && plugins.ga_count === true ? <span class="level-item" class="ga_count_container_page_pv" path={page.path} dangerouslySetInnerHTML={{
 __html: _p('plugin.visit_count', '<span id="ga_count_value_page_pv">0</span>')
}}></span> : null}

接着要修改插件的脚本,主要是通过dom操作获取到该页面所有class name是ga_count_container_page_pv的dom对象,提取path attribute然后组装并请求,最后将结果设置到dom对象中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
document.addEventListener("DOMContentLoaded", function () {
    let counterDivs = document.getElementsByClassName('ga_count_container_page_pv');
    if (counterDivs.length == 0) {
        return;
    }
    let pathList = [];
    for (let index = 0; index < counterDivs.length; index++) {
        pathList.push(counterDivs[index].getAttribute('path'));
    }
    fetch('http://后端地址/batch', { method: 'post', body: JSON.stringify({ path: pathList }) }).then(response => response.json())
        .then(json => {
            for (let index = 0; index < counterDivs.length; index++) {
                counterDivs[index].getElementsByTagName('span')[0].innerText = json.pv[index]
            }
        })
});

效果预览

这样在主页中就能显示每篇文章的访问量了,会更加直观一点。
由于这行字太长了,移动端会出现横向的滚动条,看了下上面这行浅灰色的字是包裹在flex布局中,我加上了flex-wrap,去掉了其他无关紧要的东西,个人感觉换行比滚动条直观吧。
桌面端效果
移动端效果

后记

这次总算把这个弄到了自己的博客上,计划下次再基于这些东西做个热门文章的功能。

作者

ZhongHuihong

发布于

2021-10-11

更新于

2021-10-11

许可协议